/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Copyright 2002-2003 by Mark Wolgemuth, All rights reserved.             */
/* Copyright 2002-2003 by Employease, Inc.  All rights reserved.           */
/*                                                                         */
/* Redistribution and use in source and binary forms, with or without      */
/* modification, are permitted provided that the following conditions      */
/* are met:                                                                */
/*                                                                         */
/*    1. Redistributions of source code must retain the above copyright    */
/* notice, this list of conditions and the following disclaimer.           */
/*    2. Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in the     */
/* documentation and/or other materials provided with the distribution.    */
/*                                                                         */
/* THIS SOFTWARE IS PROVIDED BY THE MOD_ATHENA PROJECT ``AS IS'' AND ANY   */
/* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE       */
/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR      */
/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR        */
/* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   */
/* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,     */
/* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR      */
/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY     */
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT            */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE   */
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.    */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef ATH_TYPES_H
#define ATH_TYPES_H

#include "ath_constants.h"
#include "ath_list_types.h"
/* for time, shm and mutex typedefs */
#include "apr_global_mutex.h"
#include "apr_shm.h"
#include "apr_time.h"
#include "apr_uri.h"

/* errors written to error log (or stdout/err) */
#define    ATH_ESTNDEBU        "Not compiled with status debug."
#define    ATH_ESHMNCRE        "Failed to create shm. Path: [%s]"
#define    ATH_ESHMNATA        "Failed to attach shm. Path: [%s] Size: [%ld]"
#define    ATH_ESHMEXIS        "Attaching to shm seg."
#define    ATH_EMUXMORE        "Need at least 3 mutexes."
#define    ATH_EMUXNCRE        "Failed to create mutex. Path: [%s] Mutex: [%d]"
#define    ATH_EMUXPERM        "Failed to set mutex perms. Path: [%s] Mutex: [%d]"
#define    ATH_EMUXNINI        "Failed to init mutex. Path: [%s] Mutex: [%d]"
#define    ATH_EMUXNULL        "Fatal error: lock is NULL. Path: \"%s\""
#define    ATH_EMUXLOCK        "Failed to lock mutex. Path: [%s] Mutex: [%d]"
#define    ATH_EMUXUNLO        "Failed to unlock mutex. Path: [%s] Mutex: [%d]"
#define    ATH_EENBADRE        "Malformed engine request: uri [%s] args [%s]"
#define    ATH_EALGOCNF        "Impossible config: to many algo types for dynamic."
#define    ATH_EPHYSSTR        "Received bogus serialized phys member."
#define    ATH_EFARMSTR        "Received bogus serialized farm."
#define    ATH_EEMBOVER        "Embedded reqs exceeds compiled ATH_MAX_EMBED=%d."

/* typedefs for all objs */
typedef struct ath_upd_farm ath_upd_farm;
typedef struct ath_upd_phys ath_upd_phys;
typedef struct ath_cfg_farm ath_cfg_farm;
typedef struct ath_cfg_phys ath_cfg_phys;
typedef struct ath_algo_def ath_algo_def;
typedef struct ath_farm ath_farm;
typedef struct ath_phys ath_phys;
typedef struct ath_engine_stat ath_engine_stat;
typedef struct ath_engine ath_engine;
typedef struct ath_shm_blob ath_shm_blob;
typedef struct ath_lock ath_lock;
typedef struct ath_conf_ap ath_conf_ap;
typedef enum ath_smartfarm_type ath_smartfarm_type;

/* ath_req_farm
 * values set in a farm state update request
 */
struct ath_upd_farm 
{
    ath_list *farms;
    int on;
    int on_u;
    ath_list *member_add;
    ath_list *member_rem;
    char *str_algo;
    float hit_adds;
    int hit_adds_u;
    char hit_adds_to;
    int expect;
    int expect_u;
    int ttl;
    int ttl_u;
    int rttl;
    int rttl_u;
    int smartfarmable;
    int smartfarmable_u;
    char *str_down_url;
    char *str_offline_url;
};

/* ath_req_phys
 * values set in a phys state update request
 */
struct ath_upd_phys 
{
    /* this allows us to specify a list of hosts to update 
     * since only one set of values can be used, this is only
     * useful for marking groups up or down
     */
    ath_list *physs;
    int on;
    int on_u; /* was this field updated (handle 0 problem) */
    int up;
    int up_u; 
    float cpu;
    int cpu_u;
    float net;
    int net_u;
    float ld;
    int ld_u;
    float mem;
    int mem_u;
    float disk;
    int disk_u;
    float cus0;
    int cus0_u;
    float cus1;
    int cus1_u;
    float cus2;
    int cus2_u;
    float cus3;
    int cus3_u;
    float cus4;
    int cus4_u;
    float cus5;
    int cus5_u;
    float cus6;
    int cus6_u;
    float cus7;
    int cus7_u;
    float cus8;
    int cus8_u;
    float cus9;
    int cus9_u;
};

/* ath_cfg_farm 
 * values set in runtime config directives
 */
struct ath_cfg_farm 
{
    int on;
    char *name;
    char *down_url;
    char *offline_url;
    char *algo_str;
    float hit_adds;
    char hit_adds_to;
    int expect_update;
    int allow_ttl;
    int recover_ttl;
    int max_excluded;
    int smartfarmable;
    ath_list *members;
};

/* ath_cfg_phys
 * values set in runtime config directives
 */
struct ath_cfg_phys 
{
    int on;
    char *host;
};

/* ath_algo_def
 * algoritm definition
 */
struct ath_algo_def 
{
    /* if rr is set, all else ignored */
    int round_robin;
    /* set to type code ATH_CPU etc. or ATH_NON for none */
    char simple; 
    /* set to type code by or-ing algo codes */
    /* will indicate which measurements to include in calculation */
    char dynamic[ATH_ALGO_FIELDS]; /* padded by ATH_NON case */
    int max_excluded;
};
  
/* ath_farm shm struct
 * real farm structure
 * structured this way to properly use shm segment
 * no ptrs since shm mappings into proc space may vary 
 * write access is syncronized. dirty reads configureabl.
 */
struct ath_farm 
{
    int idx; /* my own index in the shm farm array */
    int exists;
    char name[ATH_NAME_MAX];
    char down_url[ATH_NAME_MAX];
    char offline_url[ATH_NAME_MAX];
    ath_algo_def algo_def[1]; /* [1] creates ptr */
    float hit_adds;
    char hit_adds_to;
    int on;
    int expect_update;
    int allow_ttl;
    int recover_ttl;
    int smartfarmable;
    int member_chosen_idx;
    int member_phys_idx[ATH_PHYS_HARDMAX + 1]; /* pad with -1 at end */
    int lock_idx;
};

/* ath_phys shm struct
 * real structure representing a server to be used in farms
 * structured this way to properly use shm segment
 * no ptrs since shm mappings into proc space may vary 
 * write access is syncronized. dirty reads configureable.
 */
struct ath_phys 
{
    int idx; /* my own index in the shm phys array */
    int exists;
    char host[ATH_NAME_MAX];
    /* "online" (on) on "up" are two ways to control if a phys is 
     * available to be chosen.
     * "up" is an indication of its ABILITY to serve requests,
     *     it is a health status that is set externally, independent of
     *     timeout, via some monitoring tool
     * "in" is an internal tracking of ABILITY to server requests,
     *     it obeys the rules of expect update and recover ttl
     *     which are in turn used to determine a phys's health
     * "on" (online) indicates that it is ALLOWED to answer requests.
     *     there may be times when a server passes the ability test,
     *     but that you would rather it not answer requests.
     *     there is no automatic changing of this setting, only manual.
     * each server must be both UP and ON and IN to receive a request.
     */
    int on;
    int up;
    int in; /* not timed out = 1 */
    apr_int64_t mtime;
    apr_int64_t dtime;  
    float cpu;
    float net;
    float ld;
    float mem;
    float disk;
    float ping;
    float cus0;
    float cus1;
    float cus2;
    float cus3;
    float cus4;
    float cus5;
    float cus6;
    float cus7;
    float cus8;
    float cus9;
    int membership_idx[ATH_FARM_HARDMAX + 1]; /* pad with -1 at end */
    int lock_idx;

};

struct ath_engine_stat 
{
    apr_int64_t hits_hello;
    apr_int64_t hits_reject;
    apr_int64_t hits_error; 
    apr_int64_t hits_status;
    apr_int64_t hits_update;
    apr_int64_t hits_balance;
    apr_int64_t hits_downurl;
    apr_int64_t hits_offlineurl;
    apr_int64_t hits_mirror;
    apr_int64_t hits_smartfarm;
    apr_int64_t hits_smartfarm_tamper;
/*     apr_int64_t hits_smartfarm_undef; */
/*     apr_int64_t hits_smartfarm_broken; */
/*     apr_int64_t hits_smartfarm_prepend; */
/*     apr_int64_t hits_smartfarm_postpend; */
/*     apr_int64_t hits_smartfarm_replace; */
/*     apr_int64_t hits_smartfarm_sticky; */
/*     apr_int64_t hits_smartfarm_blind; */
/*     apr_int64_t hits_smartfarm_match; */
/*     apr_int64_t hits_smartfarm_regex; */
    /* good engine hits = sum farm hits */
    apr_int64_t hits_idx_farm[ATH_FARM_HARDMAX];
    apr_int64_t hits_idx_phys[ATH_PHYS_HARDMAX];
};

/* ath_engine shm struct
 * shared engine status container 
 */
struct ath_engine 
{
    char path[ATH_NAME_MAX];
    char down_url[ATH_NAME_MAX];
    char offline_url[ATH_NAME_MAX];
    ath_algo_def algo_def[1]; /* so it creates a ptr */
    float hit_adds;
    char hit_adds_to;
    int default_phys_on;
    int default_farm_on;
    int expect_update;
    char expect_update_field;
    int nominate_per_update;
    int allow_ttl;
    int recover_ttl;
    int smartfarming;
    int farm_count;
    int phys_count;
    int lock_idx; /* currently not used */
    ath_engine_stat stats[1];
};


/* this container obj allows us to avoid offset arithmetic */
struct ath_shm_blob 
{
    ath_farm farm[ATH_FARM_HARDMAX];
    ath_phys phys[ATH_PHYS_HARDMAX];
    ath_engine engine[1]; /* so it creates a ptr */
};

struct ath_lock 
{
    char *path;
    int idx;
    apr_global_mutex_t *mux;
};

struct ath_conf_ap 
{
    ath_list *farm_cfgs;       /* all preconfig farm names */
    ath_list *phys_cfgs;       /* all preconfig physical names */
    apr_size_t shm_size;
    const char *shm_path;      /* path shm seg */
    const char *mux_prefix;    /* path shm seg */
    int diverse_multi;
    int allow_mirror;
    int mux_count;             /* number of muxes */
    int phys_count;            /* count physicals in conf file */
    int farm_count;            /* count farms in conf file */
    char read_only;
    int engine_allow_ttl;      /* seconds to live w/o heartbeat */
    int engine_recover_ttl;
    int engine_on;             /* on or off (off)*/
    int engine_default_phys_on;
    int engine_default_farm_on;
    const char *engine_path;   /* path athena engine */
    const char *engine_down_url;
    int engine_down_url_force_get;
    const char *engine_offline_url;
    int engine_offline_url_force_get;
    const char *engine_algo;   /* algo def string */
    char engine_hit_adds_to;
    float engine_hit_adds;
    int engine_expect_update;  /* ... */
    char engine_expect_update_field;
    int engine_nominate_per_update;
    int engine_max_excluded;
    const char *engine_status_farmfmt;
    const char *engine_status_physfmt;
    const char *engine_status_engifmt;
    const char *cookie_name_smartfarm;
    int smartfarm_enable;
    const char *smartfarm_hashdata;
    const char *smartfarm_tamper_url;
};

enum ath_smartfarm_type 
  {
      ATH_SFARM_TAMPER,
      ATH_SFARM_BROKEN,
      ATH_SFARM_UNDEF,
      ATH_SFARM_PREPEND,
      ATH_SFARM_POSTPEND,
      ATH_SFARM_REPLACE,
      ATH_SFARM_STICKY,
      ATH_SFARM_BLIND,
      ATH_SFARM_MATCH,
      ATH_SFARM_REGEX
  };
  
#endif // ATH_TYPES_H


